package com.blue.common.handler;

import com.alibaba.fastjson.JSON;
import com.blue.common.entity.LoginUserInfo;
import com.blue.common.entity.ResponseResult;
import com.blue.common.exception.AuthorException;
import com.blue.common.exception.CustomException;
import com.blue.common.exception.OfflineException;
import com.blue.common.utils.ThreadLocalUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    //通用异常处理
    @ExceptionHandler(CustomException.class)
    public ResponseResult<?> CustomException(CustomException e) {
        log.warn(e.getMessage());
        return ResponseResult.errorResult(e.getMessage());
    }

    //权限异常处理
    @ExceptionHandler(AuthorException.class)
    public ResponseResult<?> AuthorException(AuthorException e) {
        log.warn(e.getMessage());
        return ResponseResult.errorResult(401, e.getMessage());
    }

    //离线异常处理
    @ExceptionHandler(OfflineException.class)
    public ResponseResult<?> OfflineException(OfflineException e) {
        log.warn(e.getMessage());
        return ResponseResult.errorResult(402, e.getMessage());
    }

    //系统异常处理
    @ExceptionHandler(Exception.class)
    public ResponseResult<?> exception(Exception e) {
        ResponseResult<Object> result = ResponseResult.errorResult(e.getMessage());
        Map<String, Object> map = new HashMap<>();
        LoginUserInfo loginUserInfo = ThreadLocalUtils.getLoginUserInfo();
        if (loginUserInfo != null) {
            map.put("requestUrl", loginUserInfo.getPath());
            map.put("params", loginUserInfo.getParams());
            map.put("operator", loginUserInfo.getUserId());
        }
        String stack = getExceptionStack(e);
        String[] logs = stack.split("\r\n\t");
        StringBuilder errorDetail = new StringBuilder();
        if (logs.length > 0) {
            map.put("errorType", logs[0]);
            for (String log : logs) {
                if (log.contains("com.blue")) {
                    errorDetail.append(log).append("\n");
                }
            }
        }
        map.put("traceId", result.getTraceId());
        map.put("errorDetail", errorDetail.toString());
        rabbitTemplate.convertAndSend("errorLogsExchange", "errorLogsKey", JSON.toJSONString(map));
        log.error("请求失败，异常:{}", e.getMessage());
        return result;
    }

    /**
     * 将异常的堆栈信息转成String
     */
    public String getExceptionStack(Throwable throwable) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        throwable.printStackTrace(pw);
        return sw.toString();
    }
}
